import sys
import json
from PyQt5.QtWidgets import (
    QWidget,
    QHBoxLayout,
    QPushButton,
    QMessageBox,
    QVBoxLayout,
    QComboBox,
)
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt
from abc import ABC, abstractmethod, ABCMeta
from pydantic import ValidationError
import gui.controls.envs as envs
from . import message_box as MBox


# 创建一个新的元类来解决冲突
class MetaClass(type(QWidget), ABCMeta):
    pass


class CParamComponent(QWidget, ABC, metaclass=MetaClass):
    before_save_signal = pyqtSignal(object)
    return_save_result_signal = pyqtSignal(object)

    def __init__(self, parent=None):
        super(CParamComponent, self).__init__(parent)
        self.before_save_signal.connect(self.before_save_handler)
        # self.hLayout = QHBoxLayout()

        self.model = self.get_model()
        if self.model is None:
            raise ValueError("子类必须通过 get_model() 方法设置 model")

        # self.pBtnConfirm = QPushButton("确认")
        # self.pBtnConfirm.setObjectName("pBtnAdd")
        # self.pBtnConfirm.clicked.connect(self.on_pBtnConfirm_clicked)
        # self.pBtnCancel = QPushButton("取消")
        # self.pBtnCancel.setObjectName("pBtnEdit")
        # self.pBtnCancel.clicked.connect(self.on_pBtnCancel_clicked)

        # self.pBtnConfirm.setFixedHeight(30)
        # self.pBtnConfirm.setMinimumWidth(80)
        # self.pBtnCancel.setFixedHeight(30)
        # self.pBtnCancel.setMinimumWidth(80)

        # self.hLayout.setAlignment(Qt.AlignCenter)  # 设置居中对齐
        # self.hLayout.addWidget(self.pBtnConfirm)
        # self.hLayout.addWidget(self.pBtnCancel)
        self.layout = QVBoxLayout()
        self.hLayout = QHBoxLayout()
        # paramsLayout = QHBoxLayout()

        self.btnLayout = QVBoxLayout()
        self.pBtnDel = QPushButton("从库删除")
        self.pBtnDel.setObjectName("pBtnDel")
        self.pBtnDel.clicked.connect(self.on_pBtnDel_clicked)
        self.pBtnSave = QPushButton("保存到库")
        self.pBtnSave.setObjectName("pBtnSave")
        self.pBtnSave.clicked.connect(self.on_pBtnSave_clicked)
        self.btnLayout.setAlignment(Qt.AlignBottom)  # 设置居中对齐

        self.pBtnDel.setFixedHeight(30)
        self.pBtnDel.setMinimumWidth(110)
        self.pBtnSave.setFixedHeight(30)
        self.pBtnSave.setMinimumWidth(110)

        self.btnLayout.addWidget(self.pBtnDel)
        self.btnLayout.addWidget(self.pBtnSave)

        # self.hLayout.addLayout(paramsLayout)
        self.hLayout.addLayout(self.btnLayout)

        self.layout.addLayout(self.hLayout)

        self.setLayout(self.layout)

    @abstractmethod
    def get_model(self):
        """
        抽象方法：子类必须实现此方法来设置数据模型
        Returns:
            返回一个 Pydantic model 类
        """
        pass

    @abstractmethod
    def get_widgetDict(self):
        """
        抽象方法：子类必须实现此方法来返回widget字典
        Returns:
            返回一个 包含widget 字典
        """
        pass

    def updateUi(self, data):
        pass

    def on_pBtnDel_clicked(self):
        pass

    def on_pBtnSave_clicked(self):
        return self.validateParams()

    def before_save_handler(self):
        """
        这是一个可以在子类中重写的方法（也可以不重写）。
        如果子类没有重写这个方法，将不会调用这个方法。
        """
        # 在这里添加保存前的处理逻辑
        result = self.validateParams()
        # 重新发送信号，包含验证结果
        self.return_save_result_signal.emit(result)

    def validateParams(self, patch=None):
        try:
            field_values = {}
            for field_name, widget in self.get_widgetDict().items():
                if isinstance(widget, QPushButton):
                    continue
                field_info = self.model.model_fields[field_name]
                if isinstance(widget, QComboBox):
                    enum_type = field_info.annotation
                    selected_text = widget.currentText()
                    enum_value = next(
                        (
                            item.value
                            for item in enum_type
                            if item.alias == selected_text
                        ),
                        None,
                    )
                    if not enum_value and field_info.is_required():
                        raise ValueError(f"'{field_info.description}' 不能为空")
                    field_values[field_info.alias] = enum_value  # 使用 alias
                else:
                    text_value = widget.text().strip()
                    if not text_value and field_info.is_required():
                        raise ValueError(f"'{field_info.description}' 不能为空")
                    field_values[field_info.alias] = text_value  # 使用 alias

            # 使用 pydantic 进行验证
            validated_data = self.model(**field_values)
            return validated_data.model_dump()

        except ValidationError as e:
            for error in e.errors():
                field = error["loc"][0]
                # 通过 alias 反查找字段名
                field_name = next(
                    (
                        name
                        for name, info in self.model.model_fields.items()
                        if info.alias == field
                    ),
                    field,
                )
                field_description = self.model.model_fields[field_name].description
                # 获取自定义错误信息或使用默认翻译
                error_msg = str(error["msg"]).replace("Value error,", "")
                # QMessageBox.warning(self, "警告", f"{field_description}: {error_msg}")
                MBox.warning(f"{field_description}: {error_msg}")
                return False
        except ValueError as e:
            # QMessageBox.warning(self, "警告", str(e))
            MBox.warning(str(e))
            return False

    def clearValue(self):
        for _, widget in self.get_widgetDict().items():
            if isinstance(widget, QComboBox):
                widget.setCurrentIndex(0)
            else:
                widget.setText("")
